package megalopolis.server;

import java.io.IOException;
import java.net.Socket;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.LinkedList;

import megalopolis.common.ManagableThread;
import megalopolis.net.Request;
import megalopolis.net.Response;

/**
 * User: Kirill
 * Date: 19.02.2008
 */
public class NetworkThread extends ManagableThread implements NetworkHandler {

	private final Set<Player> players;

	private final Map<Player, List<Request>> queue;

	public NetworkThread() {
		super(10);
		queue = new HashMap<Player, List<Request>>();
		players = new HashSet<Player>();
	}

	public void addPlayer(Socket socket) {
		synchronized (players) {
			try {
				players.add(new Player(socket));
			} catch (IOException e) {
				// can't create Player over socket, don't worry, he will be back
			}
		}
	}

	public void threadStep() {
		synchronized (players) {
			Iterator<Player> playerIterator = players.iterator();
			while (playerIterator.hasNext()) {
				Player player = playerIterator.next();
				Request request = null;
				try {
					request = player.getNextRequest();
				} catch (IOException e) {
					// something wrong with getting request, so close connection...
					playerIterator.remove();

					// ...and remove all request from this player
					synchronized (queue) {
						queue.remove(player);
					}
				}
				if (request != null) {
					synchronized (queue) {
						List<Request> requests = queue.get(player);
						if (requests == null) {
							requests = new LinkedList<Request>();
							queue.put(player, requests);
						}
						requests.add(request);
					}
				}
			}
		}
	}

	public void sendResponse(Player player, Response response) {
		player.sendResponse(response);
	}

	public Map<Player, List<Request>> getNextRequestPortion() {
		synchronized (queue) {
			Map<Player, List<Request>> ret = new HashMap<Player, List<Request>>(queue);
			queue.clear();
			return ret;
		}
	}

}
